package ru.amse.tsyganov.jumleditor.model;


/**
 * A transition is a directed relationship between 
 * a source state vertex and a target state vertex.
 * 
 * @author Dmitry Tsyganov
 *
 */
public class Transition extends ModelElement {
	/**
	 * Usage applies only to transitions leading 
	 * into or out of an object flow state. It has 
	 * a value of uses or modifies. A value of uses 
	 * indicates that the action of the state at 
	 * the other end of the transition from the object 
	 * flow state uses but does not modify the object 
	 * represented by the object flow state. A value 
	 * of modifies indicates that the action of the 
	 * state at the other end of the transition from 
	 * the object flow state modifies and may use the 
	 * object represented by the object flow state.
	 */
	//private Usage usage;
	
	/**
	 * Designates the originating state vertex 
	 * (state or pseudostate) of the transition.
	 */
	private StateVertex source;
	
	/**
	 * Designates the target state vertex that 
	 * is reached when the transition is taken.
	 */
	private StateVertex target;

	public Transition(
			StateVertex sourceVertex, 
			StateVertex targetVertex) {
		
		if (sourceVertex == null || targetVertex == null ||
				sourceVertex == targetVertex) {
			throw new IllegalArgumentException();
		}
		
		source = sourceVertex;
		target = targetVertex;
		
		sourceVertex.getOutgoing().add(this);
		targetVertex.getIncoming().add(this);
	}
	
	public StateVertex getSource() {
		assert source != null;
		return source;
	}

	public void setSource(StateVertex sourceVertex) {
		
		if (sourceVertex == null) {
			throw new IllegalArgumentException();
		}
		
		assert source.getOutgoing().contains(this);
		
		source.getOutgoing().remove(this);
		source = sourceVertex;
		source.getOutgoing().add(this);
		
		assert source.getOutgoing().contains(this);
	}

	public StateVertex getTarget() {
		assert target != null;
		return target;
	}

	public void setTarget(StateVertex targetVertex) {
		
		if (targetVertex == null) {
			throw new IllegalArgumentException();
		}
		
		assert target.getIncoming().contains(this);
		
		target.getIncoming().remove(this);
		target = targetVertex;
		target.getIncoming().add(this);
		
		assert target.getIncoming().contains(this);
	}
	
	public void removeBindings() {
		target.getIncoming().remove(this);
		source.getOutgoing().remove(this);
	}
}
